package nl.rug.ai.believer.model;

import java.util.ArrayList;

/**
 * This class represents a world. Each world has a name, and an ArrayList of values that represent 
 * propositional letters than hold true in this world.
 * @author S1849700
 *
 */
public class World {
	
	private String name;
	private ArrayList<String> values = new ArrayList<String>();
	
	/**
	 * constructor, used to set up the world
	 * @param name - desired name of the world
	 */
	World(String name) {
		if (name == null) {
			throw new NullPointerException("Contstructor name of World was null");
		}
		this.name = name;
	}
	
	/**
	 * copy constructor
	 * @param other - the world to copy
	 */
	World(World other) {
		name = new String(other.name);
		values = new ArrayList<String>(other.values);
	}
	
	/**
	 * accessor method for name
	 * @return the name of the world
	 */
	public String getName() {
		return name;
	}
	
	/**
	 * Be sure this is only called on a world that is not added to any state yet.
	 * @param name
	 */
	void setName(String name) {
		this.name = name;
	}
	
	/**
	 * method used to add a proposition to this world. All added propositions are 
	 * always true.
	 * @param value - the proposition to add. 
	 */
	public void addProposition(String value) {
		if (value == null) {
			throw new NullPointerException();
		}
		for (String temp : Util.reservedKeywords) {
			// check if the new string contains any keyword.
			if (value.indexOf(temp) != -1) {
				throw new RuntimeException("Value for \"" + temp + 
						"\" is a subset of \"" + value + "\""); 
			}
		}
		values.add(value);
	}
	
	/**
	 * method used to remove (make false) a proposition again.
	 * @param value -- the proposition to be removed.
	 */
	public void removeProposition(String value) {
		values.remove(value);
	}
	
	/**
	 * Method used to check if a certain proposition is true or false in this world.
	 * @param value - the proposition to check.
	 * @return -- true or false, depending on whether the proposition exists or not. (true if it does)
	 */
	public boolean containsProposition(String value) {
		return values.contains(value);
	}
	
	/**
	 * We consider a World equal if their name is equal.
	 * @see Object#equals(Object)
	 */
	@Override 
	public boolean equals(Object other) {
	    //check for self-comparison
	    if ( this == other ) {
	    	return true;
	    }
	    // this renders an explicit check for "other == null" redundant, since it does the check for 
	    // null already - "null instanceof [type]" always returns false. 
	    if (!(other instanceof World)) {
	    	return false;
	    }
	    World otherWorld = (World)other;
	    // we ignore values of this world here, as the name is supposed to be a unique identifier.
	    return otherWorld.name.equals(name);
	}
	
	/**
	 * @see Object#hashCode(Object)
	 */
	// must be overwritten if .equals is overwritten. (And should be based on the same key fields.)
	@Override 
	public int hashCode() {
		return name.hashCode();
	}
}
